<template>
  <div class="input-number-range" :class="{ 'is-disabled': disabled }">
    <div class="flex">
      <div class="from">
        <!--
          blur:最小值失焦事件
          focus:最小值聚焦事件
          input:最小值输入事件
          change:最小值change事件
          -->
        <el-input
          ref="input_from"
          v-model="userInputForm"
          :disabled="disabled"
          placeholder="最小值"
          @blur="handleBlurFrom"
          @focus="handleFocusFrom"
          @input="handleInputFrom"
          @change="handleInputChangeFrom"
        />
      </div>
      <div class="center">
        <span>至</span>
      </div>
      <div class="to">
        <!--
          blur:最大值失焦事件
          focus:最大值聚焦事件
          input:最大值输入事件
          change:最大值change事件
          -->
        <el-input
          ref="input_to"
          v-model="userInputTo"
          :disabled="disabled"
          placeholder="最大值"
          @blur="handleBlurTo"
          @focus="handleFocusTo"
          @input="handleInputTo"
          @change="handleInputChangeTo"
        />
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'InputNumberRange',

  /** 组件接收参数 */
  props: {
    value: { required: true },

    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },

    // 精度参数
    precision: {
      type: Number,
      default: 0,
      validator(val) {
        return val >= 0 && val === parseInt(val, 10)
      }
    }
  },

  data() {
    return {
      userInputForm: null, // 最小值
      userInputTo: null // 最大值
    }
  },

  watch: {
  /** 监听value实现双向绑定 */
    value: {
      immediate: true,
      handler(value) {
        // 判断是否为数字number类型
        if (value instanceof Array && this.precision !== undefined) {
          const fromVal =
            value[0] && typeof value[0] === 'number' ? value[0] : null
          const toVal =
            value[1] && typeof value[1] === 'number' ? value[1] : null
          this.userInputForm = fromVal || null
          this.userInputTo = toVal || null
        }
      }
    }
  },

  methods: {
    // 根据精度保留数字
    toPrecision(num, precision) {
      if (precision === undefined) precision = 0
      return parseFloat(
        Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision)
      )
    },

    /** 触发以下事件时自动向上冒泡执行(通过emit将事件抛给element input组件) */
    handleBlurFrom(event) {
      this.$emit('blurfrom', event)
    },

    handleFocusFrom(event) {
      this.$emit('focusfrom', event)
    },

    handleBlurTo(event) {
      this.$emit('blurto', event)
    },

    handleFocusTo(event) {
      this.$emit('focusto', event)
    },

    handleInputFrom(value) {
      this.$emit('inputfrom', value)
      this.userInputFrom = value
    },

    handleInputTo(value) {
      this.$emit('inputto', value)
      this.userInputTo = value
    },

    // from输入框change事件
    handleInputChangeFrom(value) {
      const newVal = this.setPrecisionValue(value)
      this.userInputForm = newVal
      // 如果初始化数字的精度不符合代码设置时重置数字
      this.userInputTo = this.setPrecisionValue(this.userInputTo)
      if (!this.userInputForm && !this.userInputTo) {
        this.$emit('input', [])
        this.$emit('changefrom', newVal)
        return
      }

      if (!this.userInputTo) {
        this.userInputForm = newVal
      } else {
        // 最小值大于最大值时逻辑判断
        this.userInputForm =
          !newVal || parseFloat(newVal) <= parseFloat(this.userInputTo)
            ? newVal
            : this.userInputTo
      }
      this.$emit('input', [this.userInputForm, this.userInputTo])
      this.$emit('changefrom', newVal)
    },

    // to输入框change事件
    handleInputChangeTo(value) {
      const newVal = this.setPrecisionValue(value)
      this.userInputTo = newVal
      this.userInputForm = this.setPrecisionValue(this.userInputForm)
      if (!this.userInputTo && !this.userInputForm) {
        this.$emit('input', [])
        this.$emit('changefrom', newVal)
        return
      }

      if (!this.userInputForm) {
        this.userInputTo = newVal
      } else {
        // 最大值小于最小值时逻辑判断
        this.userInputTo =
          !newVal || parseFloat(newVal) >= parseFloat(this.userInputForm)
            ? newVal
            : this.userInputForm
      }
      this.$emit('input', [this.userInputForm, this.userInputTo])
      this.$emit('changeto', newVal)
    },

    // 设置成精度数字
    setPrecisionValue(value) {
      if (!value) return null
      const newVal = Number(value)
      // 如果是非数字空返回null
      if (isNaN(value)) return null
      if (typeof newVal === 'number' && this.precision !== undefined) {
        const val = this.toPrecision(value, this.precision)
        return val
      }
      return null
    }
  }
}
</script>

<style lang="scss" scoped>
// 取消element原有的input框样式
::v-deep .el-input .el-input__inner {
  border: 0px;
  margin: 0;
  padding: 0 15px;
  background-color: transparent;
  text-align: center;
}

.input-number-range {
  display: inline-block;
  background-color: #fff;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}

.flex {
  display: flex;
  flex-direction: row;
  width: 100%;
  justify-content: center;
  align-items: center;
  .center {
    margin-top: 1px;
  }
}

.is-disabled {
  background-color: #f5f7fa;
  border-color: #e4e7ed;
  color: #c0c4cc;
  cursor: not-allowed;
}
</style>
